﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;

namespace YArchitech.Plumbing
{
	internal class Detector
	{
		public Detector(Document rvtDoc)
		{
			this.m_rvtDoc = rvtDoc;
			FilteredElementIterator elementIterator = new FilteredElementCollector(this.m_rvtDoc).OfClass(typeof(View3D)).GetElementIterator();
			elementIterator.Reset();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				this.m_view3d = (element as Autodesk.Revit.DB.View3D);
				if (this.m_view3d != null && !this.m_view3d.IsTemplate)
				{
					break;
				}
			}
		}

		public List<ReferenceWithContext> Obstructions(Line boundLine)
		{
			List<ReferenceWithContext> list = new List<ReferenceWithContext>();
			XYZ endPoint = boundLine.GetEndPoint(0);
			XYZ endPoint2 = boundLine.GetEndPoint(1);
			XYZ xyz = (endPoint2 - endPoint).Normalize();
			ReferenceIntersector referenceIntersector = new ReferenceIntersector(this.m_view3d);
            referenceIntersector.TargetType = (FindReferenceTarget)16;
			foreach (ReferenceWithContext referenceWithContext in referenceIntersector.Find(endPoint, xyz))
			{
				Reference reference = referenceWithContext.GetReference();
				Element element = this.m_rvtDoc.GetElement(reference);
				if (element is Pipe || element is Duct)
				{
					Line line = (element.Location as LocationCurve).Curve as Line;
					XYZ xyz2 = line.GetEndPoint(1) - line.GetEndPoint(0);
					xyz2 = xyz2.Normalize();
					if ((xyz2.IsAlmostEqualTo(xyz) || xyz2.IsAlmostEqualTo(-xyz)) && boundLine.Distance(reference.GlobalPoint) < 1E-09 && !this.InArray(list, referenceWithContext))
					{
						list.Add(referenceWithContext);
					}
				}
			}
			foreach (ReferenceWithContext referenceWithContext2 in referenceIntersector.Find(endPoint2, -xyz))
			{
				Reference reference2 = referenceWithContext2.GetReference();
				Element element2 = this.m_rvtDoc.GetElement(reference2);
				if (element2 is Pipe || element2 is Duct)
				{
					Line line2 = (element2.Location as LocationCurve).Curve as Line;
					XYZ xyz3 = line2.GetEndPoint(1) - line2.GetEndPoint(0);
					xyz3 = xyz3.Normalize();
					if ((xyz3.IsAlmostEqualTo(xyz) || xyz3.IsAlmostEqualTo(-xyz)) && boundLine.Distance(reference2.GlobalPoint) < 1E-09 && !this.InArray(list, referenceWithContext2))
					{
						list.Add(referenceWithContext2);
					}
				}
			}
			list.Sort(new Comparison<ReferenceWithContext>(this.CompareReferencesWithContext));
			return list;
		}

		private bool InArray(List<ReferenceWithContext> arr, ReferenceWithContext entry)
		{
			foreach (ReferenceWithContext referenceWithContext in arr)
			{
				if (Math.Abs(referenceWithContext.Proximity - entry.Proximity) < 1E-09 && referenceWithContext.GetReference().ElementId == entry.GetReference().ElementId)
				{
					return true;
				}
			}
			return false;
		}

		private int CompareReferencesWithContext(ReferenceWithContext a, ReferenceWithContext b)
		{
			if (a.Proximity > b.Proximity)
			{
				return 1;
			}
			if (a.Proximity < b.Proximity)
			{
				return -1;
			}
			return 0;
		}

		private Document m_rvtDoc;

		private View3D m_view3d;
	}
}
